// 用两个栈实现队列（模拟队列）
#include "./model/stack.h"

/**
 * 入队时：
 * 1. 若enterStack满，outStack空，则使enterStack逐一弹出并压入到outStack中，再压入新元素至enterStack
 * 2. 若enterStack不满，则直接压入新元素至enterStack即可
 * 3. 若enterStack满且outStack非空，则不可进行入队操作
 * 不过这里的栈会自动扩容，因此上述1,3情况不存在，但是考试的时候需要知晓
 */
/**
 * 出队时：
 * 1. 若outStack非空，则直接从outStack弹出即可
 * 2. 若outStack为空但是enterStack不为空，则使enterStack逐一弹出并压入到outStack中，然后从outStack弹出
 * 3. 两个栈都为空，则不作任何操作
 */
/// @brief 模拟队列，两个栈分别模拟入队操作和出队操作
typedef struct
{
	Stack *enterStack;
	Stack *outStack;
} MockQueue;

/// @brief 创建一个空的模拟队列
/// @return 模拟队列指针
MockQueue *createMockQueue()
{
	MockQueue *queue = (MockQueue *)malloc(sizeof(MockQueue));
	queue->enterStack = initStack();
	queue->outStack = initStack();
	return queue;
}

/// @brief 模拟队列元素入队
/// @param queue 模拟队列对象指针
/// @param data 入队的元素
void mockEnter(MockQueue *queue, char data)
{
	push(queue->enterStack, data);
}

/// @brief 模拟队列元素出队
/// @param queue 模拟队列对象指针
/// @return 出队的元素
char mockOut(MockQueue *queue)
{
	// outStack不为空
	if (!stackEmpty(queue->outStack))
	{
		return pop(queue->outStack);
	}
	// 两者为空则不进行操作
	if (stackEmpty(queue->enterStack))
	{
		return 0;
	}
	// 否则就是enterStack非空，逐一搬到outStack再弹出
	while (!stackEmpty(queue->enterStack))
	{
		push(queue->outStack, pop(queue->enterStack));
	}
	return pop(queue->outStack);
}

int main()
{
	MockQueue *queue = createMockQueue();
	mockEnter(queue, 'A');
	mockEnter(queue, 'B');
	mockEnter(queue, 'C');
	printf("%c", mockOut(queue));
	mockEnter(queue, 'D');
	printf("%c", mockOut(queue));
	printf("%c", mockOut(queue));
	printf("%c", mockOut(queue));
	return 0;
}